﻿using System;
using System.Collections.Generic;
using System.IO;

using Microsoft.Xna.Framework;

namespace AlfarEngine.Components
{
    public class AnimationData
    {
        public float    speed;
        public float    numberOfFrame;
        public int      line;
        public float    timePerFrame;
        public string   name;

        public void Serialize(BinaryWriter pFile)
        {
            pFile.Write(speed);
            pFile.Write(numberOfFrame);
            pFile.Write(line);
            pFile.Write(timePerFrame);
            pFile.Write(name);
        }

        public void Deserialize(BinaryReader pFile)
        {
            speed = pFile.ReadSingle();
            numberOfFrame = pFile.ReadSingle();
            line = pFile.ReadInt32();
            timePerFrame = pFile.ReadSingle();
            name = pFile.ReadString();
        }
    }

    public class AnimatedSprite : Sprite
    {
        #region Variables

        private Dictionary<string, AnimationData> mAnimations;

        private int mCurrentframe;
        private string mCurrentAnimation;
        private double mTimeOfAnim;

        #endregion

        //-------------------------------------------

        #region Accessors
        #endregion

        //----------------------------------------------

        #region Methods

        public AnimatedSprite(GameObject pOwner)
            : base(pOwner)
        {
            mAnimations = new Dictionary<string, AnimationData>();
            mCurrentframe = 0;
            mCurrentAnimation = "";
            mTimeOfAnim = 0;
        }

        //*************************************************

        public override void Update(Microsoft.Xna.Framework.GameTime pTime)
        {
            if (mCurrentAnimation != "")
            {
                mTimeOfAnim += pTime.ElapsedGameTime.TotalSeconds;

                if(mTimeOfAnim >= mAnimations[mCurrentAnimation].timePerFrame)
                {//we need to go to the next frame
                    mTimeOfAnim = 0;
                    mCurrentframe++;

                    if (mCurrentframe >= mAnimations[mCurrentAnimation].numberOfFrame)
                        mCurrentframe = 0;

                    mSourceRect = new Rectangle(mCurrentframe * mSourceRect.Value.Width, mSourceRect.Value.Y, mSourceRect.Value.Width, mSourceRect.Value.Height);
                }              
            }
        }

        //**************************************************

        public override void Serialize(System.IO.BinaryWriter pFile)
        {
            base.Serialize(pFile);

            pFile.Write(mAnimations.Count);

            foreach (AnimationData lData in mAnimations.Values)
            {
                lData.Serialize(pFile);
            }
        }

        public override void Deserialize(BinaryReader pFile)
        {
            base.Deserialize(pFile);

            int lCount = pFile.ReadInt32();
            for (int i = 0; i < lCount; i++)
            {
                AnimationData lData = new AnimationData();
                lData.Deserialize(pFile);
                mAnimations[lData.name] = lData;
            }
        }

        //**************************************************

        public void AddAnimation(string pName, float pSpeed, float pNumberOfFrame, int pLine)
        {
            mAnimations[pName] = new AnimationData();
            mAnimations[pName].name = pName;
            mAnimations[pName].speed = pSpeed;
            mAnimations[pName].numberOfFrame = pNumberOfFrame;
            mAnimations[pName].line = pLine;

            mAnimations[pName].timePerFrame = pSpeed / pNumberOfFrame;
        }

        //***************************************************

        public void Play(string pName)
        {
            if (!mAnimations.ContainsKey(pName))
                throw new Exception("Animation : " + pName + " unknow");

            mCurrentAnimation = pName;
            mCurrentframe = 0;
            mTimeOfAnim = 0;


            mSourceRect = new Rectangle(0, mAnimations[pName].line * mSourceRect.Value.Height, mSourceRect.Value.Width, mSourceRect.Value.Height);
        }

        //****************************************************

        public AnimationData this[string index]
        {
            get
            {
                if(!mAnimations.ContainsKey(index))
                    return null;

                return mAnimations[index];
            }
        }

        #endregion
    }
}
